package simulacao;


import simulacao.Bot;
import swarm.Globals;
import swarm.Selector;
import swarm.defobj.Zone;

import swarm.activity.Activity;
import swarm.activity.ActionGroup;
import swarm.activity.ActionGroupImpl;
import swarm.activity.Schedule;
import swarm.activity.ScheduleImpl;

import swarm.objectbase.Swarm;
import swarm.objectbase.VarProbe;
import swarm.objectbase.MessageProbe;
import swarm.objectbase.EmptyProbeMapImpl;

import swarm.gui.Colormap;
import swarm.gui.ColormapImpl;
import swarm.gui.ZoomRaster;
import swarm.gui.ZoomRasterImpl;


import swarm.simtoolsgui.GUISwarmImpl;

import swarm.space.Value2dDisplayImpl;
import swarm.space.Object2dDisplay;
import swarm.space.Object2dDisplayImpl;
import swarm.space.Value2dDisplay;


public class BotObserverSwarm extends GUISwarmImpl
{

    public int displayFrequency = 1;
    private Schedule _displaySchedule;
    private BotModelSwarm _botModelSwarm;
    public BotModelSwarm getBotModelSwarm (){ 
        return _botModelSwarm;
    }

    private Colormap _colormapMundo;
    private Colormap _colormapMemo;

    private ZoomRaster _worldRaster;
    private ZoomRaster _memoryRaster;


    private Object2dDisplay _botDisplay;
//private Object2dDisplay _wallDisplay;
    private Value2dDisplay _memoryDisplay;

    public BotObserverSwarm (Zone aZone)
    {
        super(aZone);
        _botModelSwarm = new BotModelSwarm (getZone ());

        EmptyProbeMapImpl botObserverProbeMap = new EmptyProbeMapImpl(aZone, getClass ());

        Globals.env.probeLibrary.setProbeMap$For(botObserverProbeMap, getClass ());

    }

    public Activity activateIn (Swarm swarmContext){
        super.activateIn (swarmContext);
        _botModelSwarm.activateIn (this);
        _displaySchedule.activateIn (this);
        return getActivity();
    }

    public Object buildActions ()
    {
        super.buildActions();
        _botModelSwarm.buildActions();

        ActionGroup updateActions = new ActionGroupImpl (getZone());
        ActionGroup tkActions = new ActionGroupImpl (getZone());

        try {
            updateActions.createActionTo$message (this, new Selector (getClass (), "_update_", false));
            updateActions.createActionTo$message (Globals.env.probeDisplayManager,
                    new Selector (Globals.env.probeDisplayManager.getClass (), "update", true));
            tkActions.createActionTo$message (getActionCache (),
                    new Selector (getActionCache ().getClass (), "doTkEvents", true));
        } catch (Exception e) {
            System.err.println ("Exception in setting up tkActions : "+ e.getMessage ());
        }
        _displaySchedule = new ScheduleImpl (getZone (), displayFrequency);
        _displaySchedule.at$createAction (0, updateActions );
        _displaySchedule.at$createAction (0, tkActions );
        return this;
    }

    public Object buildObjects ()
    {
        super.buildObjects ();
        Globals.env.createArchivedProbeDisplay(_botModelSwarm, "_botModelSwarm");
        Globals.env.createArchivedProbeDisplay (this, "botObserverSwarm");
        getControlPanel ().setStateStopped ();
        _botModelSwarm.buildObjects ();

        // Criando Colormap para o labirinto:
        _colormapMundo = new ColormapImpl (getZone ());
        //Definindo as cores para os elementos da simulação:
        // 0 - Fundo - Preto
        // 1 - Bot colaborador - Azul
        // 2 - Bot inimigo - Vermelho
        // 3 - Saída - Verde
        // 4 - Parede - Branco

        _colormapMundo.setColor$ToName((byte)0, "black");
        _colormapMundo.setColor$ToName((byte)1, "blue");
        _colormapMundo.setColor$ToName((byte)2, "red");
        _colormapMundo.setColor$ToName((byte)3, "green");
        _colormapMundo.setColor$ToName((byte)4, "white");

        // Criando Colormap para a Memória:
        _colormapMemo = new ColormapImpl (getZone ());
        _colormapMemo.setColor$ToName((byte)0, "black"); //fundo
        _colormapMemo.setColor$ToName((byte)1, "white"); //muro
        _colormapMemo.setColor$ToName((byte)2, "blue"); //passagem identificada
        _colormapMemo.setColor$ToName((byte)50, "red"); //saída
        
        //tons de verde identificando quantas vezes foi vizitada determinada célula

        for (int i=3;i<15;i++)
            _colormapMemo.setColor$ToRed$Green$Blue((byte)i, 0, (double)i/15, 0);
        

        //Janela de memória....
        //
        //
        // Criando janela para exibir estado da memória:
        _memoryRaster = new ZoomRasterImpl (getZone (), "_memoryRaster");
        try {
            _memoryRaster.enableDestroyNotification$notificationMethod(this,
                    new Selector (getClass (), "_memoryRasterDeath_", false));
        } catch (Exception e) {
            System.err.println ("Exception _memoryRasterDeath_: " + e.getMessage ());
        }
        _memoryRaster.setColormap (_colormapMemo);
        _memoryRaster.setZoomFactor (8);
        _memoryRaster.setWidth$Height((_botModelSwarm.getWorld ()).getSizeX (),
                (_botModelSwarm.getWorld ()).getSizeY ());
        _memoryRaster.setWindowTitle ("Memória");
        _memoryRaster.pack();

    
        try {
            _memoryDisplay = new Value2dDisplayImpl(getZone(), _memoryRaster, _colormapMemo,
                    BotModelSwarm.getMemo());

        } catch (Exception e) {
            System.err.println ("Exception drawSelfOn: " + e.getMessage ());
        }

        /*
        try
        {
            _memoryRaster.setButton$Client$Message(3, _memoryDisplay,
                    new Selector (_memoryDisplay.getClass (), "makeProbeAtX$Y", true));
        } catch (Exception e){
            System.err.println ("aaaaaaaaaaaaaaException makeProbeAtX$Y: " + e.getMessage ());
        }
        */


        //Janela do Labirinto
        //
        //
        _worldRaster = new ZoomRasterImpl (getZone (), "_worldRaster");
        try {
            _worldRaster.enableDestroyNotification$notificationMethod (this,
                    new Selector (getClass (), "_worldRasterDeath_", false));
        } catch (Exception e) {
            System.err.println ("Exception _worldRasterDeath_: " + e.getMessage ());
        }
        _worldRaster.setColormap (_colormapMundo);
        _worldRaster.setZoomFactor (12);
        _worldRaster.setWidth$Height ((_botModelSwarm.getWorld ()).getSizeX (),
                (_botModelSwarm.getWorld ()).getSizeY ());
        _worldRaster.setWindowTitle ("Labirinto");
        _worldRaster.pack();

        try
        {
            _botDisplay = new Object2dDisplayImpl(getZone(), _worldRaster, _botModelSwarm.getWorld(),
                    new Selector (Class.forName ("simulacao.Bot"), "drawSelfOn", false));
        } catch (Exception e) {
            System.err.println ("Exception drawSelfOn: " + e.getMessage ());
        }

        try {
            _worldRaster.setButton$Client$Message(3, _botDisplay,
                    new Selector (_botDisplay.getClass (), "makeProbeAtX$Y", true));
        } catch (Exception e) {
            System.err.println ("Exception makeProbeAtX$Y: " + e.getMessage ());
        }

        return this;
    }

    @Override
    public void drop () {
        if (_worldRaster != null)
            _worldRaster.disableDestroyNotification ();
        super.drop ();
    }

    public Object _update_ () {
        //return this;
        
        if (_worldRaster != null) {
            _worldRaster.erase();
            _memoryRaster.erase();
            _botDisplay.display ();
            _memoryDisplay.display();
            _worldRaster.drawSelf ();
            _memoryRaster.drawSelf ();
        }
        return this;
        
    }

    public Object _worldRasterDeath_ (Object caller)
    {
        _worldRaster.drop ();
        _worldRaster = null;
        return this;
    }
    public Object _memoryRasterDeath_ (Object caller)
    {
        _memoryRaster.drop ();
        _memoryRaster = null;
        return this;
    }

    private VarProbe probeVariable (String name)
    {
        return Globals.env.probeLibrary.getProbeForVariable$inClass
         (name, BotObserverSwarm.this.getClass ());
    }

    private MessageProbe probeMessage (String name) {
        return Globals.env.probeLibrary.getProbeForMessage$inClass
         (name, BotObserverSwarm.this.getClass ());
    }

}
